package com.errol.sync.sync;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.renjia.supervise.config.UkerServerProperties;
import com.renjia.supervise.mapper.sync.DatabaseSyncMapper;
import com.renjia.supervise.service.sync.pojo.EntityInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author zhang xiao bin
 * @version v1.0
 * @date 2021/07/05
 * @since v
 **/
@Slf4j
@Service
public class DatabaseSyncServiceImpl implements com.renjia.supervise.service.sync.DatabaseSyncService {

    private final DatabaseSyncMapper databaseSyncMapper;
    private final UkerServerProperties ukerServerProperties;

    public DatabaseSyncServiceImpl(DatabaseSyncMapper databaseSyncMapper,
                                   UkerServerProperties ukerServerProperties) {
        this.databaseSyncMapper = databaseSyncMapper;
        this.ukerServerProperties = ukerServerProperties;
    }

    @DS("slave")
    @Override
    public List<Map<String, Object>> loadData(String selectClause, String whereClause) {
        return databaseSyncMapper.loadData(selectClause + " " + whereClause);
    }

    @DS("slave")
    @Override
    public <E> List<E> loadData(EntityInfo<E> entityInfo, String selectClause, String whereClause) {
        List<Map<String, Object>> dataList = loadData(selectClause, whereClause);
        List<E> entities = new ArrayList<>();
        try {
            for (Map<String, Object> map : dataList) {
                E entity = entityInfo.getEntityClass().getDeclaredConstructor().newInstance();
                for (EntityInfo.FieldInfo fieldInfo : entityInfo.getFieldInfos()) {
                    fieldInfo.getSetter().invoke(entity, map.get(fieldInfo.getPropertyName()));
                }
            }
        } catch (Exception e) {
            log.error("构造对象异常", e);
        }
        return entities;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public <E> void fullSync(EntityInfo<E> entityInfo, List<Map<String, Object>> data, boolean useFieldName) {
        databaseSyncMapper.deleteAll(entityInfo.getTableName());
        insertBatch(entityInfo, data, useFieldName);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public <E> void incrSync(EntityInfo<E> entityInfo, List<Map<String, Object>> data, boolean useFieldName, LocalDate rangeLft, LocalDate rangeRight, List<String> existIds) {
        if (!existIds.isEmpty()) {
            databaseSyncMapper.deleteByIds(entityInfo.getTableName(), existIds);
        }
        if (rangeRight == null) {
            rangeRight = rangeLft;
        }
        databaseSyncMapper.deleteByCreateTime(entityInfo.getTableName(), rangeLft.toString() + " 00:00:00", rangeRight.toString() + " 23:59:59");
        insertBatch(entityInfo, data, useFieldName);
    }

    /**
     * 分批次批量写入，100000 条一个批次
     *
     * @param entityInfo   实体类信息
     * @param data         数据
     * @param useFieldName 是否使用表字段名
     * @param <E>          实体类型
     */
    private <E> void insertBatch(EntityInfo<E> entityInfo, List<Map<String, Object>> data, boolean useFieldName) {
        if (!data.isEmpty()) {
            int batchSize = ukerServerProperties.getSyncBatchSize();
            // TODO: 21/8/18 避免产生大对象
            while (data.size() > batchSize) {
                databaseSyncMapper.insertBatch(entityInfo, data.subList(0, batchSize), useFieldName);
                data = data.subList(batchSize, data.size());
            }
            if (!data.isEmpty()) {
                databaseSyncMapper.insertBatch(entityInfo, data, useFieldName);
            }
        }
    }

}
